package com.openway.game.field;

import com.openway.game.personage.GameObject;


/**
 * @author Created: 04.03.12 15:52
 * @version $Date$ $Revision$
 */
public interface PlayingField {

    /**
     * Add new game object on the playing field.
     * If there is an object in this coordinate, it is removed from the field.
     *
     * @param gameObject the object to add
     * @param coordinate where to add
     * @throws com.openway.game.exception.FieldCoordinateOutOfBoundsException
     *          if coordinate is outside the field
     * @throws com.openway.game.exception.FieldStateException
     *          if this object can't be on the field
     */
    void addObject(GameObject gameObject, Coordinate coordinate);

    /**
     * Move the game object in the specified direction.
     * If next object coordinate (determined by direction) is outside the field then the object leaves the field.
     * If there is an object in the next object coordinate, it is removed from the field
     *
     * @param object    - the object to move
     * @param direction - the direction of movement
     * @return true if object is still on the field, false otherwise
     */
    public boolean moveObject(GameObject object, Direction direction);

    /**
     * Remove (if exists) object from field.
     *
     * @param gameObject - object to delete
     */
    public void removeObject(GameObject gameObject);

    /**
     * Get game object from the certain coordinate.
     *
     * @return GameObject on the specified coordinate or null if there is no object
     * @throws com.openway.game.exception.FieldCoordinateOutOfBoundsException
     *          if coordinate is outside the field
     */
    public GameObject getObject(Coordinate coordinate);

    /**
     * Get the a adjacent object by coordinate and direction.
     *
     * @return GameObject on the specified coordinate or null if there is no object
     * @throws com.openway.game.exception.FieldCoordinateOutOfBoundsException
     *          if neighboring coordinate is outside the field
     */
    GameObject getAdjacentObject(Coordinate coordinate, Direction direction);

    /**
     * Get game object coordinate.
     *
     * @return object's coordinate or null if there is no such object on the field
     */
    Coordinate getObjectCoordinate(GameObject gameObject);

    /**
     * Checks if the object goes outside the field if will follow in the direction
     *
     * @return false if object leaves the field or if there is no such object on the field,
     *         true otherwise
     */
    boolean isInsideDirection(GameObject gameObject, Direction direction);

    /**
     * Checks whether the object is lighted
     *
     * @param gameObject - object under consideration
     * @return true if object lighted,
     *         false if not or if there is no object on the field.
     */
    boolean isLighted(GameObject gameObject);

    /**
     * Returns copy of current field state.
     *
     * @return Two dimensional array that represent field's content.
     */
    GameObject[][] getFieldSnapshot();

}
